package cli.command;

import javax.print.DocFlavor;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.MalformedInputException;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Scanner;
import java.util.stream.Stream;

public class Concatenate implements Command {
    private PrintWriter out;
    private Scanner in;
    private Path currentPath;
    private List<Path> inputFiles = new ArrayList<>(); // 输入文件（默认控制台）
    private boolean append = false; // 是否追加
    private Path outputFile = null; // 输出文件（默认控制台）

    public Concatenate(PrintWriter out, Scanner in, Path currentPath) {
        this.out = out;
        this.in = in;
        this.currentPath = currentPath;
    }

    @Override
    public void handle(String[] args) throws IOException {
        int pos = 0;
        while (pos < args.length) {
            if (args[pos].equals(">") || args[pos].equals(">>"))
                break;
            Path p;
            try {
                p = currentPath.resolve(args[pos]);
                if (!Files.isRegularFile(p)) {
                    out.println(args[pos]+"不是文件！");
                    return;
                }
                if (!Files.isReadable(p)) {
                    out.println(args[pos]+"无法读取！");
                    return;
                }
            } catch (InvalidPathException e) {
                out.println(args[pos]+"路径无效！");
                return;
            }
            inputFiles.add(p);
            pos++;
        }
        if (pos < args.length) {
            append = args[pos++].equals(">>");
        }
        if (pos < args.length) {
            try {
                outputFile = currentPath.resolve(args[pos]);
                if (Files.exists(outputFile)) {
                    if (!Files.isRegularFile(outputFile)) {
                        out.println(args[pos] + "不是文件！");
                        return;
                    }
                    if (!Files.isWritable(outputFile)) {
                        out.println(args[pos] + "无法写入！");
                        return;
                    }
                }
            } catch (InvalidPathException e) {
                out.println(args[pos]+"路径无效！");
                return;
            }
            pos++;
        }
        if (inputFiles.isEmpty()) {
            List<String> standardInput = new ArrayList<>();
            while (true) {
                String s = in.nextLine();
                if (s.equals(":wq"))
                    break;
                if (s.equals(":q"))
                    return;
                standardInput.add(s);
            }
            if (outputFile == null) {
                standardInput.forEach(out::println);
            } else {
                Files.write(outputFile, standardInput, StandardOpenOption.WRITE, StandardOpenOption.CREATE, append ? StandardOpenOption.APPEND : StandardOpenOption.TRUNCATE_EXISTING);
            }
        } else {
            if (outputFile == null) {
                for (Path inputFile : inputFiles) {
                    out.print(new String(Files.readAllBytes(inputFile)));
                }
                out.println();
            } else {
                FileChannel outputChannel = FileChannel.open(outputFile, StandardOpenOption.WRITE, StandardOpenOption.CREATE, append ? StandardOpenOption.APPEND : StandardOpenOption.TRUNCATE_EXISTING);
                ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                for (Path inputFile : inputFiles) {
                    try {
                        FileChannel inputChannel = FileChannel.open(inputFile, StandardOpenOption.READ);
                        while (inputChannel.read(byteBuffer) != -1) {
                            byteBuffer.flip();
                            outputChannel.write(byteBuffer);
                            byteBuffer.clear();
                        }
                        inputChannel.close();
                    } catch (IOException e) {
                        out.println(inputFile + "读取失败！");
                        continue;
                    }
                }
                try {
                    outputChannel.close();
                } catch (IOException ignored) {
                }
            }
        }
    }
}
